{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "412873c9-5de0-4c4a-8580-194d15ae83ec",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/opt/anaconda3/envs/langchain_env/lib/python3.10/site-packages/gradio/components/chatbot.py:285: UserWarning: You have not specified a value for the `type` parameter. Defaulting to the 'tuples' format for chatbot messages, but this is deprecated and will be removed in a future version of Gradio. Please set type='messages' instead, which uses openai-style dictionaries with 'role' and 'content' keys.\n",
      "  warnings.warn(\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "* Running on local URL:  http://127.0.0.1:7863\n",
      "\n",
      "To create a public link, set `share=True` in `launch()`.\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div><iframe src=\"http://127.0.0.1:7863/\" width=\"100%\" height=\"500\" allow=\"autoplay; camera; microphone; clipboard-read; clipboard-write;\" frameborder=\"0\" allowfullscreen></iframe></div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": []
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[]\n",
      "[['2131', 'OpenAI2131']]\n",
      "[['2131', 'OpenAI2131'], ['231231', 'OpenAI231231']]\n"
     ]
    }
   ],
   "source": [
    "import gradio as gr\n",
    "from langchain.chains import ConversationChain\n",
    "from langchain.memory import ConversationBufferMemory\n",
    "from langchain.llms import OpenAI, Cohere  # 假设你正在使用OpenAI和Cohere模型，可根据实际需求调整\n",
    "\n",
    "\n",
    "# 处理函数\n",
    "def respond(model, birthday, question, chat_history):\n",
    "   \n",
    "    response = model+birthday+question\n",
    "    print(chat_history)\n",
    "    chat_history.append((question, response))\n",
    "    \n",
    "    return \"\", chat_history\n",
    "\n",
    "# 清除历史函数\n",
    "def clear_history():\n",
    "    return []\n",
    "\n",
    "# 使用Gradio Blocks创建应用\n",
    "with gr.Blocks() as demo:\n",
    "    chat_history = gr.Chatbot(label=\"聊天历史\")\n",
    "    \n",
    "    with gr.Row():\n",
    "        model_dropdown = gr.Dropdown([\"OpenAI\", \"Cohere\"], label=\"选择语言模型\")\n",
    "        birthday_input = gr.Textbox(placeholder=\"20010215\", label=\"生日\")\n",
    "    question_input = gr.Textbox(lines=2, placeholder=\"你的问题...\", label=\"问题\")\n",
    "    \n",
    "    submit_button = gr.Button(\"提交\")\n",
    "    clear_button = gr.Button(\"清除历史\")\n",
    "\n",
    "    submit_button.click(respond, [model_dropdown, birthday_input, question_input, chat_history], [question_input, chat_history])\n",
    "    clear_button.click(clear_history, [], [chat_history])\n",
    "\n",
    "# 启动应用\n",
    "demo.launch()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "c1e20139-eb6f-42d3-9427-6a1ff3e038d8",
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "BaseModel.__init__() takes 1 positional argument but 2 were given",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[12], line 39\u001b[0m\n\u001b[0;32m     36\u001b[0m \u001b[38;5;66;03m# 使用示例\u001b[39;00m\n\u001b[0;32m     37\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;18m__name__\u001b[39m \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m__main__\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n\u001b[0;32m     38\u001b[0m     \u001b[38;5;66;03m# 第一次对话（新会话）\u001b[39;00m\n\u001b[1;32m---> 39\u001b[0m     \u001b[38;5;28mprint\u001b[39m(\u001b[43mchain_with_history\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43minvoke\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m     40\u001b[0m \u001b[43m        \u001b[49m\u001b[43m{\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43minput\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m什么是量子计算？\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m}\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m     41\u001b[0m \u001b[43m        \u001b[49m\u001b[43mconfig\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m{\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mconfigurable\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43m{\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43msession_id\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mabc123\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m}\u001b[49m\u001b[43m}\u001b[49m\n\u001b[0;32m     42\u001b[0m \u001b[43m    \u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241m.\u001b[39mcontent)\n\u001b[0;32m     44\u001b[0m     \u001b[38;5;66;03m# 第二次对话（相同会话，会记住历史）\u001b[39;00m\n\u001b[0;32m     45\u001b[0m     \u001b[38;5;28mprint\u001b[39m(chain_with_history\u001b[38;5;241m.\u001b[39minvoke(\n\u001b[0;32m     46\u001b[0m         {\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124minput\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m能详细解释一下量子位吗？\u001b[39m\u001b[38;5;124m\"\u001b[39m},\n\u001b[0;32m     47\u001b[0m         config\u001b[38;5;241m=\u001b[39m{\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mconfigurable\u001b[39m\u001b[38;5;124m\"\u001b[39m: {\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124msession_id\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mabc123\u001b[39m\u001b[38;5;124m\"\u001b[39m}}\n\u001b[0;32m     48\u001b[0m     )\u001b[38;5;241m.\u001b[39mcontent)\n",
      "File \u001b[1;32mC:\\ProgramData\\miniconda3\\envs\\langchain_env\\lib\\site-packages\\langchain_core\\runnables\\base.py:5362\u001b[0m, in \u001b[0;36mRunnableBindingBase.invoke\u001b[1;34m(self, input, config, **kwargs)\u001b[0m\n\u001b[0;32m   5354\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21minvoke\u001b[39m(\n\u001b[0;32m   5355\u001b[0m     \u001b[38;5;28mself\u001b[39m,\n\u001b[0;32m   5356\u001b[0m     \u001b[38;5;28minput\u001b[39m: Input,\n\u001b[0;32m   5357\u001b[0m     config: Optional[RunnableConfig] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[0;32m   5358\u001b[0m     \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs: Optional[Any],\n\u001b[0;32m   5359\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Output:\n\u001b[0;32m   5360\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mbound\u001b[38;5;241m.\u001b[39minvoke(\n\u001b[0;32m   5361\u001b[0m         \u001b[38;5;28minput\u001b[39m,\n\u001b[1;32m-> 5362\u001b[0m         \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_merge_configs\u001b[49m\u001b[43m(\u001b[49m\u001b[43mconfig\u001b[49m\u001b[43m)\u001b[49m,\n\u001b[0;32m   5363\u001b[0m         \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39m{\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mkwargs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs},\n\u001b[0;32m   5364\u001b[0m     )\n",
      "File \u001b[1;32mC:\\ProgramData\\miniconda3\\envs\\langchain_env\\lib\\site-packages\\langchain_core\\runnables\\history.py:606\u001b[0m, in \u001b[0;36mRunnableWithMessageHistory._merge_configs\u001b[1;34m(self, *configs)\u001b[0m\n\u001b[0;32m    603\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(expected_keys) \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m1\u001b[39m:\n\u001b[0;32m    604\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m parameter_names:\n\u001b[0;32m    605\u001b[0m         \u001b[38;5;66;03m# If arity = 1, then invoke function by positional arguments\u001b[39;00m\n\u001b[1;32m--> 606\u001b[0m         message_history \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_session_history\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m    607\u001b[0m \u001b[43m            \u001b[49m\u001b[43mconfigurable\u001b[49m\u001b[43m[\u001b[49m\u001b[43mexpected_keys\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m]\u001b[49m\n\u001b[0;32m    608\u001b[0m \u001b[43m        \u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m    609\u001b[0m     \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m    610\u001b[0m         \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m config:\n",
      "Cell \u001b[1;32mIn[12], line 31\u001b[0m, in \u001b[0;36m<lambda>\u001b[1;34m(session_id)\u001b[0m\n\u001b[0;32m     26\u001b[0m chain \u001b[38;5;241m=\u001b[39m prompt \u001b[38;5;241m|\u001b[39m model\n\u001b[0;32m     28\u001b[0m \u001b[38;5;66;03m# 4. 添加记忆功能\u001b[39;00m\n\u001b[0;32m     29\u001b[0m chain_with_history \u001b[38;5;241m=\u001b[39m RunnableWithMessageHistory(\n\u001b[0;32m     30\u001b[0m     chain,\n\u001b[1;32m---> 31\u001b[0m     get_session_history\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mlambda\u001b[39;00m session_id: \u001b[43mChatMessageHistory\u001b[49m\u001b[43m(\u001b[49m\u001b[43msession_id\u001b[49m\u001b[43m)\u001b[49m,\n\u001b[0;32m     32\u001b[0m     input_messages_key\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124minput\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m     33\u001b[0m     history_messages_key\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mhistory\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m     34\u001b[0m )\n\u001b[0;32m     36\u001b[0m \u001b[38;5;66;03m# 使用示例\u001b[39;00m\n\u001b[0;32m     37\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;18m__name__\u001b[39m \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m__main__\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n\u001b[0;32m     38\u001b[0m     \u001b[38;5;66;03m# 第一次对话（新会话）\u001b[39;00m\n",
      "\u001b[1;31mTypeError\u001b[0m: BaseModel.__init__() takes 1 positional argument but 2 were given"
     ]
    }
   ],
   "source": [
    "from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n",
    "from langchain_core.runnables.history import RunnableWithMessageHistory\n",
    "from langchain_openai import ChatOpenAI\n",
    "from langchain_community.chat_message_histories import ChatMessageHistory\n",
    "\n",
    "# 1. 创建提示模板\n",
    "prompt = ChatPromptTemplate.from_messages([\n",
    "    (\"system\", \"你是一个有用的助手\"),\n",
    "    MessagesPlaceholder(variable_name=\"history\"),  # 历史消息占位符\n",
    "    (\"human\", \"{input}\")  # 用户输入\n",
    "])\n",
    "\n",
    "# 2. 初始化 OpenAI 模型\n",
    "SILICONFLOW_API_KEY = \"sk-meosqmudzxwgifmudetqprzpkmyrmhqldplltusymdeugmue\"\n",
    "model = ChatOpenAI(\n",
    "                model=\"deepseek-ai/DeepSeek-R1-Distill-Qwen-32B\",\n",
    "                temperature=0.4,\n",
    "                max_tokens=None,\n",
    "                timeout=None,\n",
    "                max_retries=2,\n",
    "                api_key=SILICONFLOW_API_KEY,\n",
    "                base_url=\"https://api.siliconflow.cn/v1\",\n",
    "            )\n",
    "\n",
    "# 3. 构建基础链\n",
    "chain = prompt | model\n",
    "\n",
    "# 4. 添加记忆功能\n",
    "chain_with_history = RunnableWithMessageHistory(\n",
    "    chain,\n",
    "    get_session_history=lambda session_id: ChatMessageHistory(session_id),\n",
    "    input_messages_key=\"input\",\n",
    "    history_messages_key=\"history\",\n",
    ")\n",
    "\n",
    "# 使用示例\n",
    "if __name__ == \"__main__\":\n",
    "    # 第一次对话（新会话）\n",
    "    print(chain_with_history.invoke(\n",
    "        {\"input\": \"什么是量子计算？\"},\n",
    "        config={\"configurable\": {\"session_id\": \"abc123\"}}\n",
    "    ).content)\n",
    "\n",
    "    # 第二次对话（相同会话，会记住历史）\n",
    "    print(chain_with_history.invoke(\n",
    "        {\"input\": \"能详细解释一下量子位吗？\"},\n",
    "        config={\"configurable\": {\"session_id\": \"abc123\"}}\n",
    "    ).content)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3c38ad0e-3bcb-4e31-8689-3020553271be",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.16"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
